//#define __FORCE_TRACE__
//#define __FORCE_DEBUG__
//#define __FORCE_INFO__
#define THIS_FILE "ia\fn_ambush.sqf"
#include <tmf_constants.h>
#include <tmf_macros.h>

TRACE_1("Start",_this);
TMFPROFILERSTART;

private ["_grp","_mines","_ambushDist","_knowsAboutEnemy","_ambushwait","_ambush","_ambushed","_targets","_nearestEnemy","_lastDist","_minDist","_npc","_createMine","_doCreateMine"
		,"_mineposition","_roads","_rnd","_pursue","_dir_to","_i","_sleep"];
DEFAULT_PARAM(_grp,0,grpNull);
DEFAULT_PARAM(_mines,1,0);

if (AND_ALSO(OR_ELSE(IS_OBJECT(_grp),IS_GROUP(_grp)),(!isnull _grp))) then {
	if (IS_OBJECT(_grp)) then {
		_grp = group _grp;
	};
	if (!isServer && !(local (leader _grp))) exitWith { ERROR_1("Execution should be on server or local to the unit",_this); };
	if (!IS_SCALAR(_mines)) then {
		_mines = 0;
	} else {
		_mines = round(_mines);
	};

	_ambushDist = 40;
	_knowsAboutEnemy = 0.4;
	_ambushwait = 10000;
	_ambush = true;
	_ambushed = false;
	_targets = [];
	_nearestEnemy = objNull;
	_lastDist = 1000;
	_minDist = 1000;
	_sleep = 5;

	_npc = leader _grp;
	_grp setFormation "LINE";
	_npc setBehaviour "STEALTH";	
	_npc setSpeedMode "FULL";	


	_createMine = {
		private ["_npc","_rnd","_soldier","_mine","_dir","_position"];
		DEFAULT_PARAM(_soldier,0,objNull);
		DEFAULT_PARAM(_position,1,ARR_2(0,0));
			
		TRACE_1("createMine",_this);
		_mine = objnull;
		_rnd = 0;
		_dir = 0;
		_npc = leader _soldier;
		
		if (_soldier == _npc ) then {
			_rnd = floor (random ( count ((units _npc))));		
			_soldier = (units _npc) select _rnd;
		};
		
		if (!isnil "_soldier") then {
			if (!(_soldier iskindof "Man" ) || _soldier == _npc || _soldier!=vehicle _soldier || !alive _soldier || !canmove _soldier) exitwith {false};		
			
			if ((count _this) > 1) then {
				[_soldier,_position] spawn _doCreateMine;
			}else{
				[_soldier] spawn _doCreateMine;
			};
			true;
		} else {
			false;
		};
	};

	_doCreateMine = {
		private ["_npc","_rnd","_soldier","_mine","_dir","_position"];
		DEFAULT_PARAM(_soldier,0,objNull);
		DEFAULT_PARAM(_position,1,ARR_2(0,0));
		
		TRACE_1("doCreateMine",_this);

		if (count _position <= 0) exitWith { false };
		if (([_position,[0,0]] call FFUNC(distTo)) <= 1) exitWith { false };
		
		//If not is Man or dead exit
		if (!(_soldier iskindof "Man" ) || _soldier!=vehicle _soldier || !alive _soldier || !canmove _soldier) exitwith {false};		
		
		_soldier stop false;
		_soldier setUnitPos "AUTO";	
		
		if ((count _this) > 1) then {
			_soldier domove _position;
			waituntil {unitReady _soldier || moveToCompleted _soldier || moveToFailed _soldier || !alive _soldier || !canmove _soldier};
		};

		if (moveToFailed _soldier || !alive _soldier || _soldier != vehicle _soldier || !canmove _soldier) exitwith {false};	
		
		 //Crouch
		_soldier playMovenow "AmovPercMstpSlowWpstDnon_AmovPknlMstpSlowWpstDnon";
		sleep 1;
		
		if (!alive _soldier || !canmove _soldier) exitwith{};
		_position = _soldier modelToWorld [0,0.5,0];	
		_mine = createMine [(["TYPE_LANDMINE","ATMine"] call FFUNC(getFrameworkValue)), _position , [], 0];	

		//Prepare mine
		_soldier playMoveNow "AinvPknlMstpSnonWnonDr_medic";
		sleep 5;
		_soldier switchMove "";
		
		//Return to formation
		_soldier domove position ( leader _soldier );
		sleep 5;
		_soldier dofollow ( leader _soldier );
	};


	//Puts a mine if near road
	if ( _mines >= 1 ) then {
		_npc setBehaviour "careless";
		_mineposition = _npc modelToWorld [0, (_ambushDist / 1.2), 0];	 				
		_mineposition set [2, 0];
		_roads = _mineposition nearroads (_ambushDist / 1.5);
		_dir_to = getdir _npc;
		DEBUG_1("Roads",ARR_3(_grp, (count _roads), _mines));
		
		while {_mines > 0} do
		{
			_i = 0;
			if (count _roads > 0) then {
				_rnd = floor (random (count _roads));
				_mineposition = position (_roads select _rnd);
				_roads = _roads - [_roads select _rnd];
				if ([_npc,_mineposition] call _createMine) then {
					_mines = _mines -1;
					_i = 1;
				};				
			} else {
				_mineposition = [position _npc,(_dir_to + 20 -(random 40)) mod 360, (_ambushDist / 1.2 ) + random 10] call FFUNC(relPos2D);				
				_mineposition set [2, 0];
				_mineposition = [_mineposition, 5] call FFUNC(getRanPointCircle);
				if ([_npc,_mineposition] call _createMine) then {
					_mines = _mines -1;
					_i = 1;
				};	
			};
			sleep 0.1;
			if (_i != 1) then {_mines = _mines -1;} //in case no mine was set
		};
		
		_npc setBehaviour "careless";			
		sleep 30;				
		{	
			if (!stopped _x) then {
				_x domove position _npc;
				waituntil {moveToCompleted _x || moveToFailed _x || !alive _x || !canmove _x || _x distance _npc <= 5};
			};
		} foreach units _npc;				
	};				



	// did the leader die?					
	_npc = leader _grp;						
	if (!alive _npc || !canmove _npc || isplayer _npc ) exitwith {_exit=true;};		


	_grp setFormation "LINE";
	_npc setBehaviour "AWARE";
	sleep 10;



	sleep 0.1;
	_unitpos ="DOWN";
	{		
		_x setUnitPos _unitpos;	
		sleep 0.5;
		_x stop true;	
	} foreach units _npc;	
	_npc setBehaviour "STEALTH";
	
	_pursue = false;

	// -- START WAITING FOR ENEMY
	_gothit = false;
	while {alive (leader _grp) && (_pursue || _ambush)} do {
		_sleep = 5;
		_npc = leader _grp;
		{
			//_nearestEnemy = assignedTarget _x;
			_nearestEnemy = _x findnearestenemy _x;
			#ifdef __FORCE_TRACE__			
				player globalchat format["Nearest Enemy %1, know about %2",_nearestEnemy,_x knowsabout _nearestEnemy];
			#endif
			if (_x knowsabout _nearestEnemy > _knowsAboutEnemy && (_npc knowsabout _nearestEnemy <= _knowsAboutEnemy || count _targets <= 0 )) then 	{		
				
				if (_npc knowsabout _nearestEnemy <= _knowsAboutEnemy ) then 	{		 
					_npc reveal _nearestEnemy;
					if (IS_DEBUG) then {player globalchat format["%1: %2 reveals target %3 to leader",_grp,typeof _x, typeof _nearestEnemy]; diag_log Format["UPSMON: %1:  %2 reveals target %3 to leader",_grp,typeof _x, typeof _nearestEnemy];}; 	
				};
				
				//If no targets adds this
				if (count _targets <= 0) then {
					//_target = _nearestEnemy;
					_targets = _targets + [_nearestEnemy];					
					_nearestEnemy setvariable ["UPSMON_lastknownpos", position _nearestEnemy, false];						
					if (IS_DEBUG) then {player globalchat format["%1: %3 added to targets",_grp,typeof _x, typeof _target]}; 						
				};
			};
			
			if (!(alive _x) || (damage _x) > 0.2) then { _gothit = true; };
		} foreach units _grp;		
		
		if (!isnull _nearestEnemy && _ambush) then {
			// When the enemy gets closer, we control more often.
			if ((_npc distance _nearestEnemy) < _ambushDist*3) then {
				_sleep = 1;
			};
			if ((_npc distance _nearestEnemy) < _ambushDist*2) then {
				_sleep = 0.5;
			};
		};
		
		if (_ambush) then {
			_prov = ((_ambushDist*2 - (_npc distance _nearestEnemy))*3) - 20;
			//if (IS_DEBUG) then {player sidechat format["%1:%6 _ambushDist=%5 last=%2 dist=%3 prov=%4",_grp,_lastDist,_npc distance _nearestEnemy,_prov,_ambushDist,typeof _nearestEnemy]};
			
			if (_gothit  || time > _ambushwait
					|| ( "Air" countType [_nearestEnemy]<=0 
						&& (	_npc distance _nearestEnemy <= _ambushDist + random 10 
								|| (!isNull (_nearestEnemy) && (( random 100 <= _prov) && ( _npc distance _nearestEnemy > _lastDist) && (_npc distance _nearestEnemy < _ambushDist*3)))
						))
				) then {				
					sleep ((random 1) + 1); // let the enemy then get in the area 
					if (IS_DEBUG) then {player sidechat format["%1: ATTACK !",_grp]; diag_log Format["UPSMON: %1: Attack!",_grp];};
					_ambush = false;
					_ambushed = true;
					_grp setBehaviour "COMBAT";
					_grp setCombatMode "RED";
					{
						_x stop false;	
						_x setUnitPos "Auto";
						_x doFollow _npc;
					} foreach units _grp;
					_npc doMove (position _nearestEnemy);
					if (_npc distance _nearestEnemy > _ambushDist*2) then {
						_pursue = true;
					};
			};
			
			//Sets distance to target
			_lastDist = _npc distance _nearestEnemy;
			if (_lastDist > _minDist) then {
				_minDist = _lastDist;
			};
		}; // end of ambush
		
		if (_pursue) then {
			if (_npc distance _nearestEnemy > _ambushDist*2) then {
				_npc doMove (position _nearestEnemy);
			} else {
				_pursue = false;
			};
		};
		sleep _sleep;
	};
} else {
	ERROR("Invalid Parameters");
};

TRACE("End");
TMFPROFILERSTOP;